package com.zzj.ecology.system.service.impl.system;

import com.zzj.ecology.commons.consts.GlobalConstant;
import com.zzj.ecology.system.bean.system.SysPermission;
import com.zzj.ecology.system.bean.system.SysUrl;
import com.zzj.ecology.system.bean.system.SysUrlExample;
import com.zzj.ecology.system.dto.HttpResult;
import com.zzj.ecology.system.domain.Page;
import com.zzj.ecology.system.mapper.system.SysPermissionMapper;
import com.zzj.ecology.system.mapper.system.SysUrlMapper;
import com.zzj.ecology.system.service.system.SysUrlService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

import java.util.List;

/**
 * 事务相关
 * https://segmentfault.com/a/1190000015639753
 * https://www.cnblogs.com/liuzhenlei/p/6777644.html
 *
 * 在aop配置事务控制或注解式控制事务中，try...catch...会使事务失效，
 * 可在catch中抛出运行时异常throw new RuntimeException(e) 或者
 * 手动回滚TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
 * 使得事务生效，异常回滚。
 */

@Transactional(rollbackFor = Exception.class)
@Service("sysUrlService")
public class SysUrlServiceImpl implements SysUrlService {

    private final static Logger log = LoggerFactory.getLogger(SysUrlServiceImpl.class);

    @Autowired
    private SysUrlMapper sysUrlMapper;
    @Autowired
    private SysPermissionMapper sysPermissionMapper;

    /**
     * 分页查询 URL 列表数据
     * @param page
     * @return
     */
    public HttpResult findPageList(Page page) {
        int currentPage = page.getCurrentPage();
        Integer pageCounts = page.getPageCounts();
        int first = (currentPage - 1) * pageCounts;

        List<SysUrl> lists = sysUrlMapper.findPageList(first, pageCounts);
        page.getData().put(HttpResult.LIST_TAG, lists);// 当前页面数据

        SysUrlExample example = new SysUrlExample();
        SysUrlExample.Criteria criteria = example.createCriteria();
        criteria.andDeleteStatusEqualTo(GlobalConstant.DELETE_STATUS_NOT_DELETE);//delete_status='0' 的数据

        List<SysUrl> list1 = sysUrlMapper.selectByExample(example);//不分页总数据
        page.setTotalCounts(list1.size());
        return HttpResult.success().add(HttpResult.PAGE_TAG, page);
    }

    /**
     * 创建 新的 URL请求路径 并给予权限.
     * 当抛出异常时，手动回滚事务，并把返回值返回给调用者。
     * @param sysUrl
     * @param permissionId
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public HttpResult createAndGrant(SysUrl sysUrl, Integer permissionId) {
        try {
            int i = sysUrlMapper.insertSelective(sysUrl);
            if (permissionId != null) {
                reGrantPermission(sysUrl.getUrlId(), permissionId);
            }
        } catch (Exception e) {
            e.printStackTrace();
            handlerTransactionRollback();
            return HttpResult.error();
        }
        return HttpResult.success();
    }

    /**
     * 根据既存的URL请求地址的ID修改内容，并给其重新分配权限
     * @param sysUrl
     * @param permissionId
     * @return
     */
    public HttpResult updateAndGrant(SysUrl sysUrl, Integer permissionId) {
        try {
            sysUrlMapper.updateByPrimaryKeySelective(sysUrl);
            if (permissionId != null) {
                reGrantPermission(sysUrl.getUrlId(), permissionId);
            }
        } catch (Exception e) {
            e.printStackTrace();
            handlerTransactionRollback();
            log.error(e.getMessage());
            return HttpResult.error();
        }
        return HttpResult.success();
    }

    /**
     * 查询 urlPath 是否已经存在，存在 返回TRUE, 不存在返回FALSE
     * @param urlPath
     * @return
     */
    public boolean checkUrlPathExists(String urlPath) {
        SysUrlExample example = new SysUrlExample();
        example.createCriteria().andUrlPathEqualTo(urlPath);
        List<SysUrl> sysUrls = sysUrlMapper.selectByExample(example);
        return sysUrls.size() > 0 ? true : false;
    }

    /**
     * 批量修改 delete_status = '0' 修改成 '1', 记录修改人员并且修改时间
     * @param urlIds
     * @param username
     * @return
     */
    public HttpResult updateDeleteStatusByIds(List<Integer> urlIds, String username) {
        sysUrlMapper.updateDeleteStatusByIds(urlIds, username);
        return HttpResult.success();
    }


    private void reGrantPermission(Integer urlId, Integer permissionId) {
        // urlId != null 时, 更新操作; urlId == null时，是新增操作
        if (urlId != null) {
            List<SysPermission> perms = sysPermissionMapper.findUrlPermissionRelationByUrlId(urlId);
            if (perms != null && perms.size() > 0) {
                sysPermissionMapper.deleteUrlPermissionRelationByUrlId(urlId);
            }
        }
        sysPermissionMapper.insertUrlPermissionRelation(urlId, permissionId);
    }

    /**
     * 手动回滚事务
     */
    private void handlerTransactionRollback() {
        TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
    }
}
